﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Web;
using System.Web.Profile;
using System.Web.Security;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

using MP.Core.Library;
using MP.Core.Config;
using MP.Core.Authentication.Entity;

namespace MP.Core.Authentication
{
    public class MPRoleProvider : RoleProvider
    {
        #region "Variable"
        private string connectionString;
        private string applicationName;

        #endregion

        #region "Properties"
        public override string ApplicationName
        {
            get
            {
                return applicationName;
            }
            set
            {
                applicationName = value;
            }
        }
        #endregion

        public MPRoleProvider()
        {
            ProfileProvider provider = ProfileManager.Providers["MPProfileProvider"];
            applicationName = provider.ApplicationName;
            connectionString = MP.Core.Library.SqlHelper.ConnectionStringOBS;
        }

        public static MPRoleProvider CreateInstant()
        {
            return new MPRoleProvider();
        }

        #region "Override Method"
        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            // Initialize values from web.config.
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            if ((name == null) || (name.Length == 0))
            {
                name = "MPRoleProvider";
            }

            if (String.IsNullOrEmpty(config["description"]))
            {
                config.Remove("description");
                config.Add("description", "How Do I Profile provider");
            }

            // Initialize the abstract base class.
            base.Initialize(name, config);

            if ((config["applicationName"] == null) || String.IsNullOrEmpty(config["applicationName"]))
            {
                applicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
            }
            else
            {
                applicationName = config["applicationName"];
            }

            // Initialize connection string.
            ConnectionStringSettings connectionStringSettings =
              ConfigurationManager.ConnectionStrings[config["connectionStringName"]];

            if ((connectionStringSettings == null) || String.IsNullOrEmpty(connectionStringSettings.ConnectionString))
            {

                throw new Exception("Connection String cannot be blank.");
            }
            connectionString = connectionStringSettings.ConnectionString;
        }

        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            if (usernames == null || roleNames == null || usernames.Length <= 0 || roleNames.Length <= 0)
                return;

            string users = "";
            string roles = "";

            for (int i = 0; i < usernames.Length; i++)
                users += usernames[i] + ",";
            for (int i = 0; i < roleNames.Length; i++)
                roles += roleNames[i] + ",";

            string strSQL = "MP_AddUsersToRoles";
            SqlParameter[] param = new SqlParameter[3];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@UserNames", users.TrimEnd(','));
            param[2] = new SqlParameter("@RoleNames", roles.TrimEnd(','));

            SqlHelper.ExecuteNonQuery(SqlHelper.ConnectionStringOBS, CommandType.StoredProcedure, strSQL, param);
        }

        public override void CreateRole(string roleName)
        {
            if (!RoleExists(roleName))
            {
                string strSQL = "MP_CreateRole";
                SqlParameter[] param = new SqlParameter[2];
                param[0] = new SqlParameter("@ApplicationName", ApplicationName);
                param[1] = new SqlParameter("@RoleName", roleName);
                SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);

                strSQL = "Roles_CreateRole";
                param = new SqlParameter[2];
                param[0] = new SqlParameter("@RoleName", roleName);
                param[1] = new SqlParameter("@ApplicationName", ApplicationName);

                SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);
            }
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            string strSQL = "";

            strSQL = "RoleModules_DelByRoleName";
            SqlParameter[] param = new SqlParameter[2];
            param[0] = new SqlParameter("@RoleName", roleName);
            param[1] = new SqlParameter("@ApplicationName", ApplicationName);

            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);

            strSQL = "MP_DeleteRole";
            param = new SqlParameter[3];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleName", roleName);
            param[2] = new SqlParameter("@DeleteOnlyIfRoleIsEmpty", throwOnPopulatedRole);
            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);

            return true;
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            string strSQL = "MP_FindUsersInRole";
            SqlParameter[] param = new SqlParameter[3];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleName", roleName);
            param[2] = new SqlParameter("@UserNameToMatch", usernameToMatch);

            DataTable table = SqlHelper.ExecuteDataTable(SqlHelper.ConnectionStringOBS, CommandType.StoredProcedure, strSQL, param);
            if (table != null && table.Rows.Count > 0)
            {
                string[] users = new string[table.Rows.Count];
                for (int i = 0; i < table.Rows.Count; i++)
                    users[i] = table.Rows[i]["UserName"].ToString();
                return users;
            }
            return new string[0];
        }

        public override string[] GetAllRoles()
        {
            string strSQL = "MP_GetAllRoles";
            SqlParameter param = new SqlParameter("@ApplicationName", ApplicationName);
            DataTable table = SqlHelper.ExecuteDataTable(SqlHelper.ConnectionStringOBS, CommandType.StoredProcedure, strSQL, param);
            if (table != null && table.Rows.Count > 0)
            {
                string[] roles = new string[table.Rows.Count];
                for (int i = 0; i < table.Rows.Count; i++)
                    roles[i] = table.Rows[i]["RoleName"].ToString();
                return roles;
            }
            return new string[0];
        }

        public override string[] GetRolesForUser(string username)
        {
            string strSQL = "MP_GetRolesForUser";
            SqlParameter[] param = new SqlParameter[2];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@UserName", username);
            DataTable table = SqlHelper.ExecuteDataTable(SqlHelper.ConnectionStringOBS, CommandType.StoredProcedure, strSQL, param);
            if (table != null && table.Rows.Count > 0)
            {
                string[] roles = new string[table.Rows.Count];
                for (int i = 0; i < table.Rows.Count; i++)
                    roles[i] = table.Rows[i]["RoleName"].ToString();
                return roles;
            }
            return new string[0];
        }

        public override string[] GetUsersInRole(string roleName)
        {
            string strSQL = "MP_GetUsersInRoles";
            SqlParameter[] param = new SqlParameter[2];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleName", roleName);
            DataTable table = SqlHelper.ExecuteDataTable(SqlHelper.ConnectionStringOBS, CommandType.StoredProcedure, strSQL, param);
            if (table != null && table.Rows.Count > 0)
            {
                string[] users = new string[table.Rows.Count];
                for (int i = 0; i < table.Rows.Count; i++)
                    users[i] = table.Rows[i]["UserName"].ToString();
                return users;
            }
            return new string[0];
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            string strSQL = "MP_IsUserInRole";
            SqlParameter[] param = new SqlParameter[3];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@UserName", username);
            param[2] = new SqlParameter("@RoleName", roleName);

            object f = SqlHelper.ExecuteScalar(SqlHelper.ConnectionStringOBS, CommandType.StoredProcedure, strSQL, param);
            return (bool)f;
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            if (usernames == null || roleNames == null || usernames.Length <= 0 || roleNames.Length <= 0)
                return;

            string users = "";
            string roles = "";

            for (int i = 0; i < usernames.Length; i++)
                users += usernames[i] + ",";
            for (int i = 0; i < roleNames.Length; i++)
                roles += roleNames[i] + ",";

            string strSQL = "MP_RemoveUsersFromRoles";
            SqlParameter[] param = new SqlParameter[3];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@UserNames", users.TrimEnd(','));
            param[2] = new SqlParameter("@RoleNames", roles.TrimEnd(','));

            SqlHelper.ExecuteNonQuery(SqlHelper.ConnectionStringOBS, CommandType.StoredProcedure, strSQL, param);
        }

        public override bool RoleExists(string roleName)
        {
            string strSQL = "MP_RoleExists";
            SqlParameter[] param = new SqlParameter[2];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleName", roleName);

            object f = SqlHelper.ExecuteScalar(SqlHelper.ConnectionStringOBS, CommandType.StoredProcedure, strSQL, param);
            return (bool)f;
        }
        #endregion

        #region "Method"
        /// <summary>
        /// Cap nhat tinh trang Enable cua Role
        /// </summary>
        /// <param name="roleName"></param>
        public void UpdateEnable(string roleName)
        {
            //MPRoleProvider mp = new MPRoleProvider();
            string strSQL = "Roles_UpdateEnable";
            SqlParameter[] param = new SqlParameter[2];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleName", roleName);
            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);
        }

        /// <summary>
        /// Lay danh sach role
        /// </summary>
        public DataTable GetAll()
        {
            //MPRoleProvider mp = new MPRoleProvider();
            string strSQL = "Roles_GetAll";
            SqlParameter[] param = new SqlParameter[1];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            return SqlHelper.ExecuteDataTable(connectionString, CommandType.StoredProcedure, strSQL, param);
        }

        /// <summary>
        /// Lay danh sach cac modules thiet lap roles
        /// </summary>
        /// <param name="roleName"></param>
        /// <returns></returns>
        public DataTable GetSettingRole(string roleName, string moduleCode)
        {
            //MPRoleProvider mp = new MPRoleProvider();
            string strSQL = "PRC_GetSettingRoles";
            SqlParameter[] param = new SqlParameter[3];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleName", roleName);
            param[2] = new SqlParameter("@ModuleCode", moduleCode);
            return SqlHelper.ExecuteDataTable(connectionString, CommandType.StoredProcedure, strSQL, param);
        }

        /// <summary>
        /// Thiet lap role cho module
        /// </summary>
        /// <param name="ModCode">Ma module</param>
        /// <param name="Action">Hanh dong</param>
        /// <param name="Sta">Tinh trang</param>
        public void EditActionRole(string roleName, string ModCode, string Action, bool Sta)
        {
            string strSQL = "PRC_EditActionRole";
            SqlParameter[] param = new SqlParameter[5];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleName", roleName);
            param[2] = new SqlParameter("@ModCode", ModCode);
            param[3] = new SqlParameter("@Action", Action);
            param[4] = new SqlParameter("@sta", Sta);
            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);
        }

        /// <summary>
        /// Cap nhat ten role
        /// </summary>
        public void UpdateRoleName(Guid roleId, string roleName)
        {
            string strSQL = "PRC_UpdateRoleName";
            SqlParameter[] param = new SqlParameter[3];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleId", roleId);
            param[2] = new SqlParameter("@RoleName", roleName);
            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);
        }

        public void DeleteRoleAction(Guid Id)
        {
            string strSQL = "PRC_DeleteActionRole";
            SqlParameter param = new SqlParameter("@Id", Id);
            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);
        }

        public DataTable GetRolesModules(string userName)
        {
            return GetRolesModules(userName, "");
        }

        public DataTable GetRolesModules(string userName, string Module)
        {
            string strSQL = "PRC_GetRolesModules";
            SqlParameter[] param = new SqlParameter[3];
            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@UserName", userName);
            param[2] = new SqlParameter("@ModCode", Module);
            return SqlHelper.ExecuteDataTable(connectionString, CommandType.StoredProcedure, strSQL, param);
        }

        public RoleAction GetRoleAction(string userName, string Module)
        {
            RoleAction item = null;

            DataTable role = GetRolesModules(userName, Module);
            if (role != null && role.Rows.Count > 0)
            {
                item = new RoleAction();
                for (int i = 0; i < role.Rows.Count; i++)
                {
                    if (i == 0)
                    {
                        for (int j = 0; j < role.Columns.Count; j++)
                            item.Items[role.Columns[j].ColumnName] = role.Rows[i][j];
                    }
                    else
                    {
                        for (int j = 2; j < role.Columns.Count; j++)
                            item.Items[role.Columns[j].ColumnName] = Convert.ToBoolean(item.Items[role.Columns[j].ColumnName]) | Convert.ToBoolean(role.Rows[i][j]);
                    }
                }
            }

            return item;
        }

        public bool CheckRoles(string userName, string Module, string Action)
        {
            bool IsValid = false;

            DataTable table = GetRolesModules(userName, Module);
            if (table != null && table.Rows.Count > 0)
            {
                foreach (DataRow row in table.Rows)
                {
                    if (Convert.ToBoolean(row[Action]))
                    {
                        IsValid = true;
                        break;
                    }
                }
            }

            return IsValid;
        }

        public DataTable CheckRolesMenu(string userName, DataTable menu)
        {
            if (menu == null || menu.Rows.Count == 0)
                return null;
            DataTable _menu = menu.Clone();

            DataTable table = GetRolesModules(userName);
            if (table == null || table.Rows.Count == 0)
                return null;

            // Duyet qua cac menu
            foreach (DataRow mnu in menu.Rows)
            {
                // Duyet qua cac module
                if (mnu["Action"].ToString() == ".")
                {
                    DataRow r = _menu.NewRow();
                    r.ItemArray = mnu.ItemArray;
                    _menu.Rows.Add(r);
                }
                else
                {
                    foreach (DataRow row in table.Rows)
                    {
                        if (!Convert.IsDBNull(row["ModCode"]) && !string.IsNullOrEmpty(row["ModCode"].ToString())
                            && !Convert.IsDBNull(mnu["Action"]) && !string.IsNullOrEmpty(mnu["Action"].ToString())
                            && Convert.ToBoolean(row[mnu["Action"].ToString()]) && mnu["ModCode"].ToString().Equals(row["ModCode"].ToString()))
                        {

                            DataRow r = _menu.NewRow();
                            r.ItemArray = mnu.ItemArray;
                            _menu.Rows.Add(r);
                            break;
                        }
                    }
                }
            }
            return _menu;
        }

        public void UpdateRoleModule(string ModCode, Guid RoleId, Guid DepartId, bool IsShow, bool IsShowToUser, bool IsAdd, bool IsEdit, bool IsEditToUser, bool IsDelete, bool IsDeleteToUser, bool IsEnable, bool IsAll)
        {
            string strSQL = "PRC_UpdateRoleModule";
            SqlParameter[] param = new SqlParameter[13];

            param[0] = new SqlParameter("@ApplicationName", ApplicationName);
            param[1] = new SqlParameter("@RoleId", RoleId);
            param[2] = new SqlParameter("@ModCode", ModCode);
            param[3] = new SqlParameter("@DepartId", DepartId);
            param[4] = new SqlParameter("@IsShow", IsShow);
            param[5] = new SqlParameter("@IsShowToUser", IsShowToUser);
            param[6] = new SqlParameter("@IsAdd", IsAdd);
            param[7] = new SqlParameter("@IsEdit", IsEdit);
            param[8] = new SqlParameter("@IsEditToUser", IsEditToUser);
            param[9] = new SqlParameter("@IsDelete", IsDelete);
            param[10] = new SqlParameter("@IsDeleteToUser", IsDeleteToUser);
            param[11] = new SqlParameter("@IsEnable", IsEnable);
            param[12] = new SqlParameter("@IsAll", IsAll);

            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);
        }

        public int ComparePriority(string user1, string user2)
        {
            string strSQL = "MB_GetPositionLevel";
            SqlParameter[] param = new SqlParameter[3];
            param[0] = new SqlParameter("@user1", user1);
            param[1] = new SqlParameter("@user2", user2);
            param[2] = new SqlParameter("@level", SqlDbType.Int);
            param[2].Direction = ParameterDirection.Output;
            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, strSQL, param);
            return (int)param[2].Value;
        }

        #endregion
    }
}
